In some cases we will need a "settings" to transmit args, this "settings" suppose to be:

  • Containing many types, a class would be fine.
  • Can get it anywhere, better not using arguments.
  • Thread-Safe.

By the first and the second conditions, we can easily figure out a prototype like-

class Settings:
  def __init__(self):
    self.aBool = True
    self.aInt = 32
    self.aChar = 'a'
    self.aString = "HelloWorld"
    self.aIntArray = [0,3,4,1,4]
    self.aStringIntDict = {"Hello": 5, "World!": 6}
        ......
settings = Settings()

We can use it anywhere, eg.:

def aFun(x: str) -> str:
  return x + settings.aString

def anotherFun(y: int) -> int:
  return y + settings.aInt

But this is a global var and may cause problem by mistakes, eg.:

  ......
settings = aSettingFromAnotherFile()
settings.set(x=x,y=y)
  ......

In this stage, the "settings" is no longer the "settings" we said before, if we need the "settings" instance unique and always be there, I believe singleton would be the best choice.

def singleton(fun):
  ins = {}
  def getSingleton(*args,**kw):
    if fun not in ins:
      ins[fun] = fun(*args,**kw)
    return ins[fun]
  return getSingleton

@singleton
class Settings:
  def __init__(self):
    self.aBool = True
    self.aInt = 32
    self.aChar = 'a'
    self.aString = "HelloWorld"
        ......

settings = Settings()
settings.aBool = False
settings.aInt = 64
print(settings.aBool, settings.aInt)
# Output:
# False 64

otherSettings = Settings()
print(settings is otherSettings)
# Output:
# True

If your code runs fine in single thread, then I guess it's safe in multithreads too (unless you create the instance in threads).


Extra:

If you create the "settings" in threads then multiple instances might be created, we can use thread lock to solve the problem.

import threading

def singleton(Fun):
  ins = {}
  def getSingleton( *args, **kw):
    if Fun not in ins:
        getSingleton.__lock__ = threading.Lock()
        with getSingleton.__lock__:
          if Fun not in ins:
            ins[Fun] = Fun( *args, **kw)
    return ins[Fun]
  return getSingleton

@singleton
class Settings:
  def __init__(self):
    self.aBool = True
    self.aInt = 32
    self.aChar = 'a'
    self.aString = "HelloWorld"
        ......

settings = Settings()